package com.chen.auth.domain.service.impl;


import cn.dev33.satoken.secure.SaSecureUtil;
import cn.dev33.satoken.stp.SaTokenInfo;
import cn.dev33.satoken.stp.StpUtil;
import cn.dev33.satoken.util.SaResult;
import com.chen.auth.domain.constants.AuthConstant;
import com.chen.auth.domain.redis.RedisUtil;
import com.google.gson.Gson;
import com.chen.auth.common.enums.AuthUserStatusEnum;
import com.chen.auth.common.enums.IsDeletedFlagEnum;

import com.chen.auth.domain.convert.AuthUserBOConverter;
import com.chen.auth.domain.entity.AuthUserBO;

import com.chen.auth.domain.service.AuthUserDomainService;
import com.chen.auth.infra.basic.entity.*;
import com.chen.auth.infra.basic.service.*;

import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;


@Service
@Slf4j
public class AuthUserDomainServiceImpl implements AuthUserDomainService {

    @Resource
    private AuthUserService authUserService;
    @Resource
    private AuthUserRoleService authUserRoleService;
    @Resource
    private AuthRoleService authRoleService;
    @Resource
    private RedisUtil redisUtil;
    @Resource
    private AuthRolePermissionService authRolePermissionService;
    @Resource
    private AuthPermissionService authPermissionService;
    private String salt = "renzs";


    private String authPermissionPrefix = "auth.permission";

    private String authRolePrefix = "auth.role";

    private static final String LOGIN_PREFIX = "loginCode";



    @Override
    @SneakyThrows
    @Transactional(rollbackFor = Exception.class)
    public Boolean register(AuthUserBO authUserBO) {
        //校验用户是否存在
        AuthUser existAuthUser = new AuthUser();
        existAuthUser.setUserName(authUserBO.getUserName());
        //查询数据库检验用户是否存在，如果存在则return
        List<AuthUser> existUser = authUserService.queryByCondition(existAuthUser);
        if (existUser.size() > 0) {
            return true;
        }
        //密码判空
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        if (StringUtils.isNotBlank(authUser.getPassword())) {
            //使用satoken集成的md5加盐算法（摘要算法）
            authUser.setPassword(SaSecureUtil.md5BySalt(authUser.getPassword(), salt));
        }
        //设置头像
        if (StringUtils.isBlank(authUser.getAvatar())) {
            authUser.setAvatar("https://static.renzs.top/20220726130434_ba935.webp");
        }
        if (StringUtils.isBlank(authUser.getNickName())) {
            authUser.setNickName("小黑子");
        }
        authUser.setStatus(AuthUserStatusEnum.OPEN.getCode());
        authUser.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        Integer count = authUserService.insert(authUser);
        //建立一个初步的角色的关联
        AuthRole authRole = new AuthRole();
        //设置正常用户的key，通过key查询角色id
        authRole.setRoleKey(AuthConstant.NORMAL_USER);
        //查询用户角色信息
        AuthRole roleResult = authRoleService.queryByCondition(authRole);
        //获取用户角色的id
        Long roleId = roleResult.getId();
        //获取注册的用户的id
        Long userId = authUser.getId();
        AuthUserRole authUserRole = new AuthUserRole();
        //设置用户id
        authUserRole.setUserId(userId);
        //设置角色id
        authUserRole.setRoleId(roleId);
        //设置状态
        authUserRole.setIsDeleted(IsDeletedFlagEnum.UN_DELETED.getCode());
        //注册的用户信息关联角色信息
        authUserRoleService.insert(authUserRole);

        //用户注册成功将用户的权限信息写入缓存
        //创建key，根据用户的用户名建立缓存
        String roleKey = redisUtil.buildKey(authRolePrefix, authUser.getUserName());
        List<AuthRole> roleList = new LinkedList<>();
        roleList.add(authRole);
        //将用户的角色信息存入redis
        redisUtil.set(roleKey, new Gson().toJson(roleList));
        AuthRolePermission authRolePermission = new AuthRolePermission();
        //设置角色id
        authRolePermission.setRoleId(roleId);
        //查询permissionIdList（对应权限的id的集合）
        List<AuthRolePermission> rolePermissionList = authRolePermissionService.
                queryByCondition(authRolePermission);
        //使用stream流将rolePermissionList中的权限id拿到
        List<Long> permissionIdList = rolePermissionList.stream()
                .map(AuthRolePermission::getPermissionId)
                .collect(Collectors.toList());

        //根据permissionId查权限所有信息
        List<AuthPermission> permissionList = authPermissionService.queryByPermissionList(permissionIdList);
        //构建key
        String permissionKey = redisUtil.buildKey(authPermissionPrefix, authUser.getUserName());
        //在redis中设置注册的用户的的权限信息
        redisUtil.set(permissionKey, new Gson().toJson(permissionList));
        return count > 0;
    }
    /**
     * 修改用户信息
     */
    @Override
    public Boolean update(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        Integer count = authUserService.updateByUserName(authUser);
        return count > 0;
    }
    /**
     * 删除用户信息
     */
    @Override
    public Boolean delete(AuthUserBO authUserBO) {
        AuthUser authUser = AuthUserBOConverter.INSTANCE.convertBOToEntity(authUserBO);
        authUser.setIsDeleted(IsDeletedFlagEnum.DELETED.getCode());
        Integer count = authUserService.updateByUserName(authUser);
        return count > 0;
    }
    /**
     * 登录
     */
    @Override
    public SaTokenInfo doLogin(String validCode) {
        //构建key，这个key与发送验证码时构建的key一致
        String loginKey = redisUtil.buildKey(LOGIN_PREFIX, validCode);
        //通过key取出openId（openId是唯一的）
        String openId = redisUtil.get(loginKey);
//        String openId = "oMt7x6gLvn5GNtV5Sf7-BR3u-IOE";
        //如果没有输入验证码返回空
        if (StringUtils.isBlank(openId)){
            return null;
        }
        AuthUserBO authUserBO = new AuthUserBO();
        authUserBO.setUserName(openId);
        //注册用户（设置用户名为微信的openId）
        this.register(authUserBO);
        //登录（通过用户名进行登录）
        StpUtil.login(openId);
        SaTokenInfo tokenInfo = StpUtil.getTokenInfo();
        return tokenInfo;
    }
    /**
     * 获取用户信息
     */
    @Override
    public AuthUserBO getUserInfo(AuthUserBO authUserBO) {
        AuthUser authUser = new AuthUser();
        authUser.setUserName(authUserBO.getUserName());
        List<AuthUser> userList = authUserService.queryByCondition(authUser);
        if (CollectionUtils.isEmpty(userList)) {
            return new AuthUserBO();
        }
        AuthUser user = userList.get(0);
        return AuthUserBOConverter.INSTANCE.convertEntityToBO(user);
    }
    /**
     * 批量获取用户信息
     */
    @Override
    public List<AuthUserBO> listUserInfoByIds(List<String> userNameList) {
        List<AuthUser> userList = authUserService.listUserInfoByIds(userNameList);
        if (CollectionUtils.isEmpty(userList)) {
            return Collections.emptyList();
        }
        return AuthUserBOConverter.INSTANCE.convertEntityToBO(userList);
    }
}
